<template>
  <div
    ref="wrap"
    @mousemove="mouseMove"
    @mouseleave="mouseLeave"
    class="CarouselItem-content"
  >
    <div class="img">
      <div class="content" ref="img" :style="imgStyle">
        <!-- 图片 -->
        <ImageLoader
          :src="options.bigImg"
          :placeholder="options.midImg"
          :duration="500"
          @load="inpText"
        />
      </div>
    </div>

    <!-- 标题以及描述 -->
    <h2 ref="title" class="title">{{ options.title }}</h2>
    <div ref="desc" class="desc">{{ options.description }}</div>
  </div>
</template>

<script>
import ImageLoader from "@/components/ImageLoader";
export default {
  props: ["options"],
  data() {
    return {
      titleWidth: 0, // 记录初始标题宽度
      descWidth: 0, // 记录初始描述宽度
      wrapSize: null, // 记录原始的容器尺寸
      imgSize: null, // 记录图片的尺寸
      mouseX: 0, // 记录鼠标的初始位置
      mouseY: 0, // 记录鼠标的初始位置
    };
  },
  components: {
    ImageLoader,
  },
  methods: {
    // 缓动展现文字
    inpText() {
      this.$emit("load");
      // 文字设置宽度为 0，透明度为 1；
      let desc = this.$refs.desc;
      let title = this.$refs.title;
      title.style.width = 0;
      desc.style.width = 0;
      title.style.opacity = 1;
      desc.style.opacity = 1;

      // 设置过渡时间
      title.style.transition = "2s";
      desc.style.transition = "2s";

      // 强制刷新浏览器
      title.clientWidth;

      setTimeout(() => {
        this.$refs.img.style.transition = "0.3s";
      }, 0);

      // 将文字宽度设置到初始记录的宽度
      title.style.width = this.titleWidth + "px";
      desc.style.width = this.descWidth + "px";
    },
    // 获取容器和图片尺寸
    getWrapAndImdSize() {
      let wrap = this.$refs.wrap;
      let img = this.$refs.img;

      // 获取容器尺寸
      this.wrapSize = {
        width: wrap.clientWidth,
        height: wrap.clientHeight,
      };

      // 获取图片尺寸
      this.imgSize = {
        width: img.clientWidth,
        height: img.clientHeight,
      };
    },
    // 记录初始文字宽度
    getTextSize() {
      let desc = this.$refs.desc;
      let title = this.$refs.title;

      this.titleWidth = title.clientWidth;
      this.descWidth = desc.clientWidth;
    },
    // 鼠标在容器中的当前位置
    mouseMove(e) {
      let info = this.$refs.wrap.getBoundingClientRect();
      // 鼠标距离视口的位置 - 元素距离视口的位置
      this.mouseX = e.clientX - info.left;
      this.mouseY = e.clientY - info.top;
    },
    // 鼠标离开，图片回归中间位置
    mouseLeave() {
      this.mouseX = this.center.x;
      this.mouseY = this.center.y;
    },
  },
  computed: {
    // 设置图片位置
    imgStyle() {
      // 如果没有容器和图片尺寸则返回
      if (!this.wrapSize || !this.imgSize) {
        return;
      }
      let left =
        (this.mouseX / this.wrapSize.width) *
        (this.wrapSize.width - this.imgSize.width);
      let top =
        (this.mouseY / this.wrapSize.height) *
        (this.wrapSize.height - this.imgSize.height);
      return {
        transform: `translate(${left}px, ${top}px)`,
      };
    },
    // 当前居中的坐标
    center() {
      return {
        x: this.wrapSize.width / 2,
        y: this.wrapSize.height / 2,
      };
    },
  },
  mounted() {
    this.getTextSize(); // 记录文字宽度
    this.getWrapAndImdSize(); // 记录容器尺寸

    this.mouseX = this.center.x; // 设置图片初始 x 坐标
    this.mouseY = this.center.y; // 设置图片初始 y 坐标

    // 利用事件队列，来避免图片一开始加载，会从左上角过渡到中间；
    setTimeout(() => {
      this.$refs.img.style.transition = "transform 0.3s";
    }, 0);

    // 页面尺寸变化，重新设置容器尺寸
    window.addEventListener("resize", this.getWrapAndImdSize);
  },
  destroyed() {
    // 组件销毁，取消监听
    window.removeEventListener("resize", this.getWrapAndImdSize);
  },
};
</script>

<style lang="less" scoped>
@import url(~@/style/var.less);
.CarouselItem-content {
  position: relative;
  width: 100%;
  height: 100%;

  .img {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    .content {
      position: absolute;
      left: 0;
      top: 0;
      width: 110%;
      height: 110%;
    }
  }

  .desc,
  .title {
    position: absolute;
    left: 30px;
    transform: translateY(-50%);
    color: #fff;

    overflow: hidden;

    white-space: nowrap;
    letter-spacing: 4px;
    text-shadow: 1px 0px 1px #ccc, -1px 0px 1px #ccc, 0px 1px 1px #ccc,
      0px -1px 1px @dark;

    opacity: 0;
  }
  .title {
    font-size: 2em;
    top: calc(50% - 40px);
  }
  .desc {
    font-size: 1.2em;
    top: calc(50% + 20px);
  }
}
</style>